﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the Microsoft Public License (Ms-PL).
// See accompanying file License.txt or copy at http://mews.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Mews.Net.Nntp.Cache
{
    using System;
    using System.Security.Cryptography;

    /// <summary>Represents an object that observes the progress of a send/receive operation.</summary>
    /// <threadsafety static="true" instance="false"/>
    public interface ISendReceiveProgressObserver
    {
        /// <summary>During a send/receive operation, this method is called right before a connection to a host is
        /// initiated.</summary>
        /// <param name="hostName">The network name of the host.</param>
        /// <returns>An object representing the connection to the network the host is a part of, if such a connection
        /// could be made; otherwise <c>null</c>. In the former case <see cref="IDisposable.Dispose"/> will be called
        /// after disconnecting from the host. In the latter case, network connectivity is presumed to be unavailable
        /// and send/receive stops without making any other calls to methods of this interface.</returns>
        /// <remarks>Note that <see cref="IDisposable.Dispose"/> is called right after closing the connection to the
        /// host with the name <paramref name="hostName"/>. For send/receive operations involving multiple hosts that
        /// are part of the same network, client code should therefore employ some kind of connection caching.
        /// Otherwise, the network connection is needlessly closed and reestablished when switching to the next host. If
        /// a permanent connection to the network exists, the implementing class can simply return a dummy object that
        /// does not do anything in its <see cref="IDisposable.Dispose"/> implementation.</remarks>
        IDisposable OnConnecting(string hostName);

        /// <summary>During a send/receive operation, this method is called immediately after the connection to a host
        /// was successful.</summary>
        /// <param name="hostName">The network name of the host.</param>
        void OnConnected(string hostName);

        /// <summary>During a send/receive operation, this method is called every time when at least another percent of
        /// the outbound articles has been sent.</summary>
        /// <param name="percent">The total percentage of the articles that have been sent so far.</param>
        void OnSendProgressChanged(int percent);

        /// <summary>During a send/receive operation, this method is called every time when at least another percent of
        /// the headers of a group has been received.</summary>
        /// <param name="groupDisplayName">The display name of the group for which progress has changed.</param>
        /// <param name="percent">The total percentage of the headers that have been received for the group so far.
        /// </param>
        void OnHeadersProgressChanged(string groupDisplayName, int percent);

        /// <summary>During a send/receive operation, this method is called every time when at least another percent of
        /// the bodies has been received.</summary>
        /// <param name="groupDisplayName">The display name of the group for which progress has changed.</param>
        /// <param name="percent">The total percentage of the bodies that have been received for the group so far.
        /// </param>
        void OnBodiesProgressChanged(string groupDisplayName, int percent);

        /// <summary>Is called once when a send/receive operation has finished.</summary>
        /// <remarks>This method is always called, except when a previous call to <see cref="OnError"/> has returned
        /// <c>false</c>.</remarks>
        void OnFinished();

        /// <summary>Is called once when a send/receive operation has been stopped by calling
        /// <see cref="Cache.StopSendReceive"/>.</summary>
        void OnStopped();

        /// <summary>Is called once for every error that occurs during a send/receive operation.</summary>
        /// <param name="hostName">The name of the host the send/receive thread was attempting to communicate with.
        /// </param>
        /// <param name="groupName">The name of the group the send/receive thread was attempting to receive articles
        /// from.</param>
        /// <param name="exception">Contains information about the reason for the send/receive failure, see exception
        /// documentation for more information:
        /// <list type="bullet">
        /// <item><see cref="PostingNotPermittedException"/></item>
        /// <item><see cref="PostingFailedException"/></item>
        /// <item><see cref="UnknownCommandException"/>Giganews servers have been observed to send a 500 response code
        /// when an attempt is made to post a message without body. Apparently the missing body is interpreted as
        /// syntax error, which is in line with the reasons that <a href="http://www.ietf.org/rfc/rfc3977.txt">RFC
        /// 3977</a> states for a 500 response code.</item>
        /// <item><see cref="ServiceUnavailableException"/></item>
        /// <item><see cref="ServerFaultException"/></item>
        /// <item><see cref="NoSuchGroupException"/></item>
        /// <item><see cref="MissingAuthenticationException"/></item>
        /// <item><see cref="AuthenticationFailedException"/></item>
        /// <item><see cref="CryptographicException"/>: The decryption of the host account name and password failed.
        /// This usually happens when a different user attempts to send/receive to/from a non-public server than the one
        /// who has created the host entry.</item>
        /// <item><see cref="MissingPrivacyException"/></item>
        /// <item><see cref="UnexpectedResponseException"/></item>
        /// <item><see cref="HostUnreachableException"/></item>
        /// <item><see cref="ConnectionLostException"/></item>
        /// <item><see cref="WriteFailedException"/></item>
        /// <item><see cref="Exception"/>: The send/receive operation failed for an unexpected reason, see exception for
        /// more information.</item>
        /// </list></param>
        /// <returns><c>true</c> to indicate that the error was handled successfully; otherwise <c>false</c>. In the
        /// latter case the original exception is rethrown, which leads to the abnormal termination of the send/receive
        /// thread. Note that <see cref="OnFinished"/> is not called when this method returns <c>false</c>.</returns>
        bool OnError(string hostName, string groupName, Exception exception);
    }
}
